/**
 * @description 封装异步请求库
 */
import router from '@/router'
import store from '@/store'
import axios from 'axios'

let AxiosInstance = axios.create({
    baseURL: '/pangu',
    timeout: 3000
})

/**
 * 可以通过请求前的拦截实现--baseURL参数修改、实现请求头token注入、也可以实现token拦截(它是登录标识，那么如果一个用户连token都没有，那么不可以调用获取用户信息等这样的业务接口--实现请求权限拦截)
 * request是请求还没有发出去的拦截
 * use(onFulfilled?: (value: V) => V) use方法要求我们传递一个回调函数进去，然后函数有一个形参进来，要求我们返回一个传递进来的参数
 */
/**
 * 可以配置一个对象，这个对象的key就是代理地址，然后值为需要进行代理的url地址
 */
let proxyObj = {
    '/wangxiang': [
        "/city/list"
    ],
    '/dingxiang': [
        "/my/purchase/list"
    ]
}
/**
 * 可以实现token通用注入控制，有些地址不要token，有些必须有token并且要注入
 * token在哪里？--vuex里边
 */
let noTokenUrl = [
    '/user/login', '/user/validate/code', '/user/app/login', "/city/list"
]
AxiosInstance.interceptors.request.use(function(config) {
    // if (config.url === "/city/list") {
    //     config.baseURL = '/wangxiang'
    // }
    for (let name in proxyObj) {
        let it = proxyObj[name]
        if (it.includes(config.url)) {
            config.baseURL = name
            break
        }
    }

    // 实现token拦截和注入
    if (noTokenUrl.includes(config.url)) {
        return config
    } else {
        // 判断token是否存在，如果不存在--那么请求需要中断--因为axios是基于Promise封装的，所以可以返回一个错误的Promise(Promise.reject())就可以中断请求
        let token = store.getters['common/token']
        if (!token) {
            return Promise.reject({code: 0, message: '前端没有token数据，你没有缓存'})
        } else {
            config.headers.token = token
            return config
        }
    }
})

/**
 * 响应拦截--对于跳过前端拦截，然后进行的响应处理
 * 可以实现token失效处理、验证请求是否安全
 * use(onFulfilled?: (value: AxiosResponse) => AxiosResponse | Promise)
 * use方法要求传递一个参数(数据类型为一个函数A)进去，函数A会入参一个响应对象B，可以对响应对象B进行处理，然后函数A要求返回一个响应对象B或则一个Promise对象
 */
AxiosInstance.interceptors.response.use(response => {
    let {data} = response
    if (data.code === 403 && data.message === "Request information authentication failed.") {
        alert('用户非法请求，请重新登录')
        router.push('/login')
        return Promise.reject({code: 400, message: '用户非法请求，请重新登录'})
    } else {
        return response
    }
})

/**
 * 异步请求方法
 * @param {string | {url: string,data: any, params: any, method: 'POST' | 'GET' | 'DELETE' | 'PUT' | 'PATCH'}} req 
 * @returns 
 */
function ajax(req) {
    if (!req) throw new TypeError('请求参数必传')
    if (!!req.startsWith) {
        req = {url: req}
    }
    if (!req.url) throw new TypeError('url参数必传')
    // async + await 只能处理Promise.resolve（then结果）
    return new Promise(resolve => {
        AxiosInstance.request({
            url: req.url,
            method: req.method || 'POST',
            // 它是查询参数--链接在url地址传递的参数
            params: req.params || {},
            // 请求体参数
            data: req.data || {}
        }).then(({ data }) => {
            resolve(data)
        }).catch(e => {
            resolve(e)
        })
    })
}

export default ajax